package com.jml.jm_usb

import java.nio.ByteBuffer
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.min

/**
 * 高性能 SPSC 环形缓冲区（字节流）
 *
 * 线程模型：单生产者 / 单消费者。
 */
class RingByteBuffer(capacity: Int) {

    /* ---------- 基本属性 ---------- */
    private val cap: Int                  // 2 的幂容量
    private val mask: Int                 // cap - 1，用位与取模
    private val buf: ByteArray

    /* 指针 & 计数 */
    private var writePos = 0              // 写线程独占
    private var readPos  = 0              // 读线程独占
    private val size = AtomicInteger(0)   // 可见字节数（跨线程）

    init {
        require(capacity > 0) { "capacity must be > 0" }
        cap  = 1.shl(Int.SIZE_BITS - Integer.numberOfLeadingZeros(capacity - 1))
        mask = cap - 1
        buf  = ByteArray(cap)
    }

    /* ========================= 写入 ========================= */

    fun write(src: ByteBuffer, len: Int = src.remaining()) {
        ensureCapacityForWrite(len)
        var remain = len
        var wp = writePos
        while (remain > 0) {
            val chunk = min(remain, cap - (wp and mask))
            src.get(buf, wp and mask, chunk)
            wp += chunk
            remain -= chunk
        }
        writePos = wp
        size.addAndGet(len)
    }

    fun write(src: ByteArray, off: Int = 0, len: Int = src.size - off) {
        ensureCapacityForWrite(len)
        var remain = len
        var wp = writePos
        var srcOff = off
        while (remain > 0) {
            val chunk = min(remain, cap - (wp and mask))
            System.arraycopy(src, srcOff, buf, wp and mask, chunk)
            wp += chunk
            srcOff += chunk
            remain -= chunk
        }
        writePos = wp
        size.addAndGet(len)
    }

    /* ========================= 读取 ========================= */

    /** 精确读取 len 字节；不足返回 null */
    fun readExact(len: Int): ByteArray? {
        if (size.get() < len) return null
        return internalRead(len)
    }

    /** 读取至多 maxLen 字节；若没有数据返回 null */
    fun readUpTo(maxLen: Int): ByteArray? {
        val available = size.get()
        if (available == 0) return null
        return internalRead(min(available, maxLen))
    }

    /** 读取当前 **全部** 可用字节并清空缓冲；若无数据返回 null */
    fun readAll(): ByteArray? {
        val available = size.get()
        if (available == 0) return null
        return internalRead(available)
    }

    /** 仅窥视 len 字节，不移动读指针 */
    fun peek(len: Int): ByteArray? {
        if (size.get() < len) return null
        val out = ByteArray(len)
        var rp = readPos
        var dst = 0
        var remain = len
        while (remain > 0) {
            val chunk = min(remain, cap - (rp and mask))
            System.arraycopy(buf, rp and mask, out, dst, chunk)
            rp += chunk
            dst += chunk
            remain -= chunk
        }
        return out
    }

    /* ========================= 状态查询 ========================= */

    fun size(): Int      = size.get()
    fun free(): Int      = cap - size.get()
    fun capacity(): Int  = cap

    /* ----------------- 内部实现 ----------------- */

    private fun ensureCapacityForWrite(len: Int) {
        require(len <= free()) {
            "RingByteBuffer overflow: need $len, free ${free()}, capacity $cap"
        }
    }

    private fun internalRead(len: Int): ByteArray {
        val out = ByteArray(len)
        var rp = readPos
        var dst = 0
        var remain = len
        while (remain > 0) {
            val chunk = min(remain, cap - (rp and mask))
            System.arraycopy(buf, rp and mask, out, dst, chunk)
            rp += chunk
            dst += chunk
            remain -= chunk
        }
        readPos = rp
        size.addAndGet(-len)
        return out
    }
}